//
//  OosActivityParser.m
//  Oos4ios
//
//  Created by Pablo Gonzalez on 3/31/11.
//

#import "OosActivityFeedParser.h"
#import "../Atom/Feeds/OosActivityFeed.h"
#import "../Atom/Entries/OosActivityEntry.h"
#import <oos4ios/Model/OosActivity.h>
#import <oos4ios/Model/OosServiceActivityObject.h>
#import <oos4ios/Model/OosMediaActivityObject.h>
#import <oos4ios/Model/OosAvatarImage.h>


@implementation OosActivityFeedParser

static OosActivityFeedParser *instance;

+ (OosActivityFeedParser *) instance
{
	if (!instance) {
		instance = [[OosActivityFeedParser alloc] init];
	}
	return instance;
}

- (NSArray *) parseFeed:(OosFeed *)feed
{
    if ([feed isKindOfClass:[NSString class]]) {
        return [self parseJsonFeed:(id)feed];
    }
	OosActivityFeed *activityFeed = (OosActivityFeed *) feed;
	
	NSMutableArray *results = [NSMutableArray array];
	
	OosActivity *activity;
	
	NSDate *updatedDate;
	
	for (OosActivityEntry *entry in [activityFeed entries]) {
		updatedDate = [entry.updatedDate date];
		
		activity = [OosActivity createFromId: entry.identifier];
		if (!activity.updated) {
			activity.title = [entry.title stringValue];
			activity.verb = [entry.verb contentStringValue];
			activity.updated = updatedDate;
			activity.actor = [self parseActivityActor:entry.actor];
			activity.object = [self parseActivityObject:entry.object];
			activity.identifier = entry.identifier;
		}
		
		[results addObject: activity];
	}
    
    return results;
}

- (OosPersonActivityObject *) parseActivityActor:
		(OosActivityAtomActor *)atomActor
{
	
	OosActivityObject *object = [self parseActivityObject: atomActor];
	if ([object isKindOfClass: [OosPersonActivityObject class]]) {
		return (OosPersonActivityObject *) object;
	} else {
		[NSException raise:@"Not an Actor" 
					format:@"The provided ActivityActor is not a valid person"];
		return nil;
	}
}

- (OosActivityObject *) parseActivityObject:
		(OosActivityAtomObject *)atomObject
{
	OosActivityObject *object = nil;
	OosActivityType *activityType = atomObject.activityType;
	NSString *type = [activityType contentStringValue];
	
	if ([type hasSuffix: @"person"]) {
		OosPersonActivityObject *personObject;
		NSString *slug = [atomObject.slug stringValue];
		personObject = [OosPersonActivityObject objectFromUserSlug:slug];
        if (!personObject.user) {
            OosUser *user = [OosUser userFromSlug:slug];
            if (!user.nick) {
                user.nick = [atomObject.title stringValue];
            }
            if (!user.avatar) {
                user.avatar = [OosAvatarImage 
                               avatarFromPath: [atomObject.avatar stringValue]];
            }
            personObject.user = user;
        }
		object = personObject;
	} else if ([type hasSuffix:@"place"]) {
		OosServiceActivityObject *serviceObject;
		NSString *serviceSlug = [atomObject.slug stringValue];
		serviceObject = [OosServiceActivityObject 
						 objectFromServiceSlug:serviceSlug];
		object = serviceObject;
	} else if ([type hasSuffix:@"picture"]) {
		OosPictureActivityObject *pictureObject;
		NSString *identifier = [atomObject.fnv stringValue];
		pictureObject = [OosPictureActivityObject 
						 objectFromIdentifier: identifier];
		if (!pictureObject.image) {
			GDataLink *link;
//			link = [atomObject linkWithRelAttributeValue:@"alternate"];
//			OosImage *image = [OosImage imageFromPath: link.href];
            OosImage *image = [OosImage imageFromIdentifier:identifier];
            link = [atomObject linkWithRelAttributeValue:@"media"];
            image.urlString = link.href;
			image.identifier = identifier;
			pictureObject.image = image;
		}
		object = pictureObject;
	} else if ([type hasSuffix:@"video"]) {
		OosVideoActivityObject *videoObject;
		NSString *identifier = [atomObject.fnv stringValue];
		videoObject = [OosVideoActivityObject objectFromIdentifier:identifier]; 
		if (!videoObject.video) {
			GDataLink *link;
			link = [atomObject linkWithRelAttributeValue:@"alternate"];
			OosVideo *video = [OosVideo videoFromIdentifier: identifier];
			video.urlString = link.href;
			videoObject.video = video;
		}
		object = videoObject;
	} else {
		// Ignore
		return nil;
	}

	
	return object;
}

#pragma mark - json addons

- (OosActivityObject *) parseJsonActivityObject: (NSArray *) rawParameters
{
    OosActivityObject *object = nil;
    
    NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
    NSMutableDictionary *links = [NSMutableDictionary dictionary];
    
    
    for (NSDictionary *parameter in rawParameters) {
        if ([parameter isKindOfClass: [NSDictionary class]] 
            && parameter.count > 0) {
            NSString *key = [[parameter allKeys] objectAtIndex:0];
            if ([key isEqualToString:@"link"]) {
                parameter = [parameter objectForKey:@"link"];
                key = [parameter objectForKey:@"rel"];
                NSString *href = [parameter objectForKey:@"href"];
                [links setObject:href forKey:key];
            } else {
                [parameters setObject:[parameter objectForKey:key] forKey:key];
            }
        }
    }
    
    NSString *type = [parameters objectForKey:@"activity_object-type"];
    
    if ([type hasSuffix: @"person"]) {
        OosPersonActivityObject *personObject;
        NSString *slug = [parameters objectForKey:@"oos_slug"];
        personObject = [OosPersonActivityObject objectFromUserSlug:slug];
        if (!personObject.user) {
            OosUser *user = [OosUser userFromSlug:slug];
            user.nick = [parameters objectForKey:@"title"];
            user.avatar = [OosAvatarImage avatarFromPath: [parameters objectForKey:@"oos_avatar"]];
            personObject.user = user;
        }
        object = personObject;
    } else if([type hasSuffix:@"place"]) {
        OosServiceActivityObject *serviceObject;
        NSString *serviceSlug = [parameters objectForKey:@"oos_slug"];
        serviceObject = [OosServiceActivityObject objectFromServiceSlug:serviceSlug];
        object = serviceObject;
    } else if([type hasSuffix:@"picture"]) {
        OosPictureActivityObject *pictureObject;
        NSString *identifier = [parameters objectForKey:@"oos_fnv"];
        pictureObject = [OosPictureActivityObject objectFromIdentifier:identifier];
        if (!pictureObject.image) {
            NSString *media = [links objectForKey:@"media"];
            OosImage *image = [OosImage imageFromIdentifier:identifier];
            image.urlString = media;
            image.identifier = identifier;
            pictureObject.image = image;
        }
        object = pictureObject;
    } else if([type hasSuffix:@"video"]) {
        OosVideoActivityObject *videoObject;
        NSString *identifier = [parameters objectForKey:@"oos_fnv"];
        videoObject = [OosVideoActivityObject objectFromIdentifier:identifier];
        if (!videoObject.video) {
            NSString *media = [links objectForKey:@"media"];
            OosVideo *video = [OosVideo videoFromIdentifier:identifier];
            video.urlString = media;
            videoObject.video = video;
        }
        object = videoObject;
    } else {
        //ignore
        return nil;
    }
    
    return object;
}

- (OosPersonActivityObject *) parseJsonActivityActor: (NSArray *) parameters
{
    OosActivityObject *object = [self parseJsonActivityObject: parameters];
	if ([object isKindOfClass: [OosPersonActivityObject class]]) {
		return (OosPersonActivityObject *) object;
	} else {
		[NSException raise:@"Not an Actor" 
					format:@"The provided ActivityActor is not a valid person"];
		return nil;
	}
}

- (NSArray *)parseJsonFeed:(NSString *)jsonFeed
{
    NSDictionary *rawFeed = (NSDictionary *)[jsonFeed JSONValue];
    NSMutableArray *results = [NSMutableArray array];
    
    NSArray *entries = [rawFeed objectForKey:@"entries"];
    OosActivity *activity;
    NSDate *updateDate;
    NSDictionary *extensions;
    NSString *identifier;
    NSDateFormatter* formatter = [[self class] jsonFormatter];
//    NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
//    [formatter setDateFormat:@"eee MMM d HH:mm:ss zzzz yyyy"];
    for (NSDictionary *entry in entries) {
        identifier = [entry objectForKey:@"id"];
        activity = [OosActivity createFromId: identifier];
        updateDate = [formatter dateFromString:[entry objectForKey:@"updated"]];
        if (!activity.updated) {
            activity.title = [entry objectForKey:@"title"];
            extensions = [entry objectForPath:@"extensions"];
            activity.verb = [extensions objectForPath:@"activity_verb"];
            activity.updated = updateDate;
            activity.actor = [self parseJsonActivityActor:
                              [extensions objectForKey:@"activity_actor"]];
            activity.object = [self parseJsonActivityObject:
                               [extensions objectForKey:@"activity_object"]];
            activity.identifier = identifier;
        }
        [results addObject:activity];
    }
    
    return results;
}

@end
